{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Reinforcement Learning for trading"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To train a trading agent, we need to create a market environment that provides price and other information, offers trading-related actions, and keeps track of the portfolio to reward the agent accordingly."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How to Design an OpenAI trading environment"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The OpenAI Gym allows for the design, registration, and utilization of environments that adhere to its architecture, as described in its [documentation](https://github.com/openai/gym/tree/master/gym/envs#how-to-create-new-environments-for-gym). The [trading_env.py](trading_env.py) file implements an example that illustrates how to create a class that implements the requisite `step()` and `reset()` methods.\n",
    "\n",
    "The trading environment consists of three classes that interact to facilitate the agent's activities:\n",
    " 1. The `DataSource` class loads a time series, generates a few features, and provides the latest observation to the agent at each time step. \n",
    " 2. `TradingSimulator` tracks the positions, trades and cost, and the performance. It also implements and records the results of a buy-and-hold benchmark strategy. \n",
    " 3. `TradingEnvironment` itself orchestrates the process. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## A basic trading game"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To train the agent, we need to set up a simple game with a limited set of options, a relatively low-dimensional state, and other parameters that can be easily modified and extended.\n",
    "\n",
    "More specifically, the environment samples a stock price time series for a single ticker using a random start date to simulate a trading period that, by default, contains 252 days, or 1 year. The state contains the (scaled) price and volume, as well as some technical indicators like the percentile ranks of price and volume, a relative strength index (RSI), as well as 5- and 21-day returns. The agent can choose from three actions:\n",
    "\n",
    "- **Buy**: Invest capital for a long position in the stock\n",
    "- **Flat**: Hold cash only\n",
    "- **Sell short**: Take a short position equal to the amount of capital\n",
    "\n",
    "The environment accounts for trading cost, which is set to 10bps by default. It also deducts a 1bps time cost per period. It tracks the net asset value (NAV) of the agent's portfolio and compares it against the market portfolio (which trades frictionless to raise the bar for the agent)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We use the same DDQN agent and neural network architecture that successfully learned to navigate the Lunar Lander environment. We let exploration continue for 500,000 time steps (~2,000 1yr trading periods) with linear decay of ε to 0.1 and exponential decay at a factor of 0.9999 thereafter."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Imports & Settings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:13.062924Z",
     "start_time": "2020-06-22T18:55:13.060817Z"
    }
   },
   "outputs": [],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:14.873384Z",
     "start_time": "2020-06-22T18:55:13.064489Z"
    }
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "from pathlib import Path\n",
    "from time import time\n",
    "from collections import deque\n",
    "from random import sample\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib.ticker import FuncFormatter\n",
    "import seaborn as sns\n",
    "\n",
    "import tensorflow as tf\n",
    "from tensorflow.keras import Sequential\n",
    "from tensorflow.keras.layers import Dense, Dropout\n",
    "from tensorflow.keras.optimizers import Adam\n",
    "from tensorflow.keras.regularizers import l2\n",
    "\n",
    "import gym\n",
    "from gym.envs.registration import register"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:14.877440Z",
     "start_time": "2020-06-22T18:55:14.874546Z"
    }
   },
   "outputs": [],
   "source": [
    "np.random.seed(42)\n",
    "tf.random.set_seed(42)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sns.set_style('whitegrid')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:14.907979Z",
     "start_time": "2020-06-22T18:55:14.878992Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using GPU\n"
     ]
    }
   ],
   "source": [
    "gpu_devices = tf.config.experimental.list_physical_devices('GPU')\n",
    "if gpu_devices:\n",
    "    print('Using GPU')\n",
    "    tf.config.experimental.set_memory_growth(gpu_devices[0], True)\n",
    "else:\n",
    "    print('Using CPU')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:14.916091Z",
     "start_time": "2020-06-22T18:55:14.909430Z"
    }
   },
   "outputs": [],
   "source": [
    "results_path = Path('results', 'trading_bot')\n",
    "if not results_path.exists():\n",
    "    results_path.mkdir(parents=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Helper functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:14.924657Z",
     "start_time": "2020-06-22T18:55:14.917435Z"
    }
   },
   "outputs": [],
   "source": [
    "def format_time(t):\n",
    "    m_, s = divmod(t, 60)\n",
    "    h, m = divmod(m_, 60)\n",
    "    return '{:02.0f}:{:02.0f}:{:02.0f}'.format(h, m, s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Set up Gym Environment"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before using the custom environment, just like we used the Lunar Lander environment, we need to register it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:14.940606Z",
     "start_time": "2020-06-22T18:55:14.925851Z"
    }
   },
   "outputs": [],
   "source": [
    "trading_days = 252"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:14.952650Z",
     "start_time": "2020-06-22T18:55:14.941630Z"
    }
   },
   "outputs": [],
   "source": [
    "register(\n",
    "    id='trading-v0',\n",
    "    entry_point='trading_env:TradingEnvironment',\n",
    "    max_episode_steps=trading_days\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Initialize Trading Environment"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can instantiate the environment by using the desired trading costs and ticker:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:16.896410Z",
     "start_time": "2020-06-22T18:55:14.954625Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:trading_env:trading_env logger started.\n",
      "INFO:trading_env:loading data for AAPL...\n",
      "INFO:trading_env:got data for AAPL...\n",
      "INFO:trading_env:None\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "MultiIndex: 9367 entries, (Timestamp('1981-01-30 00:00:00'), 'AAPL') to (Timestamp('2018-03-27 00:00:00'), 'AAPL')\n",
      "Data columns (total 10 columns):\n",
      " #   Column   Non-Null Count  Dtype  \n",
      "---  ------   --------------  -----  \n",
      " 0   returns  9367 non-null   float64\n",
      " 1   ret_2    9367 non-null   float64\n",
      " 2   ret_5    9367 non-null   float64\n",
      " 3   ret_10   9367 non-null   float64\n",
      " 4   ret_21   9367 non-null   float64\n",
      " 5   rsi      9367 non-null   float64\n",
      " 6   macd     9367 non-null   float64\n",
      " 7   atr      9367 non-null   float64\n",
      " 8   stoch    9367 non-null   float64\n",
      " 9   ultosc   9367 non-null   float64\n",
      "dtypes: float64(10)\n",
      "memory usage: 905.0+ KB\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[42]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trading_environment = gym.make('trading-v0')\n",
    "trading_environment.env.trading_days = trading_days\n",
    "trading_environment.env.trading_cost_bps = 1e-3\n",
    "trading_environment.env.time_cost_bps = 1e-4\n",
    "trading_environment.env.ticker = 'AAPL'\n",
    "trading_environment.seed(42)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Get Environment Params"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:16.904269Z",
     "start_time": "2020-06-22T18:55:16.899993Z"
    }
   },
   "outputs": [],
   "source": [
    "state_dim = trading_environment.observation_space.shape[0]\n",
    "num_actions = trading_environment.action_space.n\n",
    "max_episode_steps = trading_environment.spec.max_episode_steps"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Define Trading Agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:16.938081Z",
     "start_time": "2020-06-22T18:55:16.907028Z"
    }
   },
   "outputs": [],
   "source": [
    "class DDQNAgent:\n",
    "    def __init__(self, state_dim,\n",
    "                 num_actions,\n",
    "                 learning_rate,\n",
    "                 gamma,\n",
    "                 epsilon_start,\n",
    "                 epsilon_end,\n",
    "                 epsilon_decay_steps,\n",
    "                 epsilon_exponential_decay,\n",
    "                 replay_capacity,\n",
    "                 architecture,\n",
    "                 l2_reg,\n",
    "                 tau,\n",
    "                 batch_size):\n",
    "\n",
    "        self.state_dim = state_dim\n",
    "        self.num_actions = num_actions\n",
    "        self.experience = deque([], maxlen=replay_capacity)\n",
    "        self.learning_rate = learning_rate\n",
    "        self.gamma = gamma\n",
    "        self.architecture = architecture\n",
    "        self.l2_reg = l2_reg\n",
    "\n",
    "        self.online_network = self.build_model()\n",
    "        self.target_network = self.build_model(trainable=False)\n",
    "        self.update_target()\n",
    "\n",
    "        self.epsilon = epsilon_start\n",
    "        self.epsilon_decay_steps = epsilon_decay_steps\n",
    "        self.epsilon_decay = (epsilon_start - epsilon_end) / epsilon_decay_steps\n",
    "        self.epsilon_exponential_decay = epsilon_exponential_decay\n",
    "        self.epsilon_history = []\n",
    "\n",
    "        self.total_steps = self.train_steps = 0\n",
    "        self.episodes = self.episode_length = self.train_episodes = 0\n",
    "        self.steps_per_episode = []\n",
    "        self.episode_reward = 0\n",
    "        self.rewards_history = []\n",
    "\n",
    "        self.batch_size = batch_size\n",
    "        self.tau = tau\n",
    "        self.losses = []\n",
    "        self.idx = tf.range(batch_size)\n",
    "        self.train = True\n",
    "\n",
    "    def build_model(self, trainable=True):\n",
    "        layers = []\n",
    "        n = len(self.architecture)\n",
    "        for i, units in enumerate(self.architecture, 1):\n",
    "            layers.append(Dense(units=units,\n",
    "                                input_dim=self.state_dim if i == 1 else None,\n",
    "                                activation='relu',\n",
    "                                kernel_regularizer=l2(self.l2_reg),\n",
    "                                name=f'Dense_{i}',\n",
    "                                trainable=trainable))\n",
    "        layers.append(Dropout(.1))\n",
    "        layers.append(Dense(units=self.num_actions,\n",
    "                            trainable=trainable,\n",
    "                            name='Output'))\n",
    "        model = Sequential(layers)\n",
    "        model.compile(loss='mean_squared_error',\n",
    "                      optimizer=Adam(lr=self.learning_rate))\n",
    "        return model\n",
    "\n",
    "    def update_target(self):\n",
    "        self.target_network.set_weights(self.online_network.get_weights())\n",
    "\n",
    "    def epsilon_greedy_policy(self, state):\n",
    "        self.total_steps += 1\n",
    "        if np.random.rand() <= self.epsilon:\n",
    "            return np.random.choice(self.num_actions)\n",
    "        q = self.online_network.predict(state)\n",
    "        return np.argmax(q, axis=1).squeeze()\n",
    "\n",
    "    def memorize_transition(self, s, a, r, s_prime, not_done):\n",
    "        if not_done:\n",
    "            self.episode_reward += r\n",
    "            self.episode_length += 1\n",
    "        else:\n",
    "            if self.train:\n",
    "                if self.episodes < self.epsilon_decay_steps:\n",
    "                    self.epsilon -= self.epsilon_decay\n",
    "                else:\n",
    "                    self.epsilon *= self.epsilon_exponential_decay\n",
    "\n",
    "            self.episodes += 1\n",
    "            self.rewards_history.append(self.episode_reward)\n",
    "            self.steps_per_episode.append(self.episode_length)\n",
    "            self.episode_reward, self.episode_length = 0, 0\n",
    "\n",
    "        self.experience.append((s, a, r, s_prime, not_done))\n",
    "\n",
    "    def experience_replay(self):\n",
    "        if self.batch_size > len(self.experience):\n",
    "            return\n",
    "        minibatch = map(np.array, zip(*sample(self.experience, self.batch_size)))\n",
    "        states, actions, rewards, next_states, not_done = minibatch\n",
    "\n",
    "        next_q_values = self.online_network.predict_on_batch(next_states)\n",
    "        best_actions = tf.argmax(next_q_values, axis=1)\n",
    "\n",
    "        next_q_values_target = self.target_network.predict_on_batch(next_states)\n",
    "        target_q_values = tf.gather_nd(next_q_values_target,\n",
    "                                       tf.stack((self.idx, tf.cast(best_actions, tf.int32)), axis=1))\n",
    "\n",
    "        targets = rewards + not_done * self.gamma * target_q_values\n",
    "\n",
    "        q_values = self.online_network.predict_on_batch(states)\n",
    "        q_values[[self.idx, actions]] = targets\n",
    "\n",
    "        loss = self.online_network.train_on_batch(x=states, y=q_values)\n",
    "        self.losses.append(loss)\n",
    "\n",
    "        if self.total_steps % self.tau == 0:\n",
    "            self.update_target()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Define hyperparameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:16.960294Z",
     "start_time": "2020-06-22T18:55:16.940891Z"
    }
   },
   "outputs": [],
   "source": [
    "gamma = .99,  # discount factor\n",
    "tau = 100  # target network update frequency"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NN Architecture"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:16.976898Z",
     "start_time": "2020-06-22T18:55:16.961660Z"
    }
   },
   "outputs": [],
   "source": [
    "architecture = (256, 256)  # units per layer\n",
    "learning_rate = 0.0001  # learning rate\n",
    "l2_reg = 1e-6  # L2 regularization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Experience Replay"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:16.981461Z",
     "start_time": "2020-06-22T18:55:16.978282Z"
    }
   },
   "outputs": [],
   "source": [
    "replay_capacity = int(1e6)\n",
    "batch_size = 4096"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### $\\epsilon$-greedy Policy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:16.990720Z",
     "start_time": "2020-06-22T18:55:16.983526Z"
    }
   },
   "outputs": [],
   "source": [
    "epsilon_start = 1.0\n",
    "epsilon_end = .01\n",
    "epsilon_decay_steps = 250\n",
    "epsilon_exponential_decay = .99"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create DDQN Agent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will use [TensorFlow](https://www.tensorflow.org/) to create our Double Deep Q-Network ."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:17.001362Z",
     "start_time": "2020-06-22T18:55:16.991955Z"
    }
   },
   "outputs": [],
   "source": [
    "tf.keras.backend.clear_session()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:17.610034Z",
     "start_time": "2020-06-22T18:55:17.002991Z"
    }
   },
   "outputs": [],
   "source": [
    "ddqn = DDQNAgent(state_dim=state_dim,\n",
    "                 num_actions=num_actions,\n",
    "                 learning_rate=learning_rate,\n",
    "                 gamma=gamma,\n",
    "                 epsilon_start=epsilon_start,\n",
    "                 epsilon_end=epsilon_end,\n",
    "                 epsilon_decay_steps=epsilon_decay_steps,\n",
    "                 epsilon_exponential_decay=epsilon_exponential_decay,\n",
    "                 replay_capacity=replay_capacity,\n",
    "                 architecture=architecture,\n",
    "                 l2_reg=l2_reg,\n",
    "                 tau=tau,\n",
    "                 batch_size=batch_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:17.615621Z",
     "start_time": "2020-06-22T18:55:17.611049Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "Dense_1 (Dense)              (None, 256)               2816      \n",
      "_________________________________________________________________\n",
      "Dense_2 (Dense)              (None, 256)               65792     \n",
      "_________________________________________________________________\n",
      "dropout (Dropout)            (None, 256)               0         \n",
      "_________________________________________________________________\n",
      "Output (Dense)               (None, 3)                 771       \n",
      "=================================================================\n",
      "Total params: 69,379\n",
      "Trainable params: 69,379\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "ddqn.online_network.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run Experiment"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Set parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:17.635835Z",
     "start_time": "2020-06-22T18:55:17.617132Z"
    }
   },
   "outputs": [],
   "source": [
    "total_steps = 0\n",
    "max_episodes = 1000"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Initialize variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:17.643974Z",
     "start_time": "2020-06-22T18:55:17.637032Z"
    }
   },
   "outputs": [],
   "source": [
    "episode_time, navs, market_navs, diffs, episode_eps = [], [], [], [], []"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualiztion"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-22T18:55:17.651693Z",
     "start_time": "2020-06-22T18:55:17.645067Z"
    }
   },
   "outputs": [],
   "source": [
    "def track_results(episode, nav_ma_100, nav_ma_10,\n",
    "                  market_nav_100, market_nav_10,\n",
    "                  win_ratio, total, epsilon):\n",
    "    time_ma = np.mean([episode_time[-100:]])\n",
    "    T = np.sum(episode_time)\n",
    "    \n",
    "    template = '{:>4d} | {} | Agent: {:>6.1%} ({:>6.1%}) | '\n",
    "    template += 'Market: {:>6.1%} ({:>6.1%}) | '\n",
    "    template += 'Wins: {:>5.1%} | eps: {:>6.3f}'\n",
    "    print(template.format(episode, format_time(total), \n",
    "                          nav_ma_100-1, nav_ma_10-1, \n",
    "                          market_nav_100-1, market_nav_10-1, \n",
    "                          win_ratio, epsilon))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Train Agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-23T00:03:36.237053Z",
     "start_time": "2020-06-22T18:55:17.652918Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  10 | 00:00:01 | Agent: -39.1% (-39.1%) | Market:   4.6% (  4.6%) | Wins: 20.0% | eps:  0.960\n",
      "  20 | 00:00:32 | Agent: -33.8% (-28.6%) | Market:  23.2% ( 41.8%) | Wins: 20.0% | eps:  0.921\n",
      "  30 | 00:01:39 | Agent: -28.9% (-19.0%) | Market:  20.6% ( 15.4%) | Wins: 16.7% | eps:  0.881\n",
      "  40 | 00:02:44 | Agent: -23.5% ( -7.2%) | Market:  21.2% ( 23.0%) | Wins: 20.0% | eps:  0.842\n",
      "  50 | 00:03:52 | Agent: -22.1% (-16.5%) | Market:  20.2% ( 16.4%) | Wins: 20.0% | eps:  0.802\n",
      "  60 | 00:05:18 | Agent: -21.5% (-18.8%) | Market:  24.5% ( 45.6%) | Wins: 21.7% | eps:  0.762\n",
      "  70 | 00:06:50 | Agent: -20.6% (-14.9%) | Market:  29.4% ( 59.3%) | Wins: 21.4% | eps:  0.723\n",
      "  80 | 00:08:40 | Agent: -20.9% (-23.3%) | Market:  27.6% ( 14.7%) | Wins: 22.5% | eps:  0.683\n",
      "  90 | 00:10:37 | Agent: -19.8% (-11.0%) | Market:  24.3% ( -2.1%) | Wins: 24.4% | eps:  0.644\n",
      " 100 | 00:12:46 | Agent: -18.2% ( -3.5%) | Market:  24.0% ( 20.9%) | Wins: 25.0% | eps:  0.604\n",
      " 110 | 00:14:59 | Agent: -14.8% ( -5.6%) | Market:  26.0% ( 25.0%) | Wins: 26.0% | eps:  0.564\n",
      " 120 | 00:16:60 | Agent: -10.6% ( 13.8%) | Market:  29.9% ( 80.6%) | Wins: 27.0% | eps:  0.525\n",
      " 130 | 00:18:48 | Agent: -11.4% (-27.3%) | Market:  36.4% ( 80.3%) | Wins: 28.0% | eps:  0.485\n",
      " 140 | 00:20:49 | Agent: -10.1% (  5.5%) | Market:  35.4% ( 13.4%) | Wins: 29.0% | eps:  0.446\n",
      " 150 | 00:22:53 | Agent:  -9.1% ( -5.9%) | Market:  37.9% ( 41.0%) | Wins: 31.0% | eps:  0.406\n",
      " 160 | 00:25:01 | Agent:  -8.0% ( -8.4%) | Market:  34.9% ( 15.7%) | Wins: 32.0% | eps:  0.366\n",
      " 170 | 00:27:13 | Agent:  -7.1% ( -5.9%) | Market:  32.7% ( 37.8%) | Wins: 32.0% | eps:  0.327\n",
      " 180 | 00:29:39 | Agent:  -6.3% (-15.2%) | Market:  37.6% ( 63.3%) | Wins: 31.0% | eps:  0.287\n",
      " 190 | 00:32:47 | Agent:  -3.1% ( 21.7%) | Market:  43.9% ( 61.3%) | Wins: 31.0% | eps:  0.248\n",
      " 200 | 00:35:38 | Agent:  -1.9% (  8.2%) | Market:  43.9% ( 20.4%) | Wins: 32.0% | eps:  0.208\n",
      " 210 | 00:38:15 | Agent:  -1.7% ( -3.2%) | Market:  45.1% ( 37.2%) | Wins: 31.0% | eps:  0.168\n",
      " 220 | 00:40:56 | Agent:  -4.4% (-13.6%) | Market:  41.2% ( 41.3%) | Wins: 31.0% | eps:  0.129\n",
      " 230 | 00:44:34 | Agent:  -1.0% (  6.5%) | Market:  35.5% ( 24.2%) | Wins: 34.0% | eps:  0.089\n",
      " 240 | 00:48:03 | Agent:   0.1% ( 16.4%) | Market:  32.7% (-14.7%) | Wins: 37.0% | eps:  0.050\n",
      " 250 | 00:51:38 | Agent:   0.6% ( -0.6%) | Market:  31.5% ( 28.6%) | Wins: 35.0% | eps:  0.010\n",
      " 260 | 00:55:07 | Agent:   5.1% ( 37.2%) | Market:  33.1% ( 31.6%) | Wins: 37.0% | eps:  0.009\n",
      " 270 | 00:58:36 | Agent:   7.8% ( 21.1%) | Market:  31.5% ( 21.8%) | Wins: 40.0% | eps:  0.008\n",
      " 280 | 01:01:57 | Agent:  10.5% ( 11.7%) | Market:  33.6% ( 84.3%) | Wins: 40.0% | eps:  0.007\n",
      " 290 | 01:05:16 | Agent:   8.3% ( -1.2%) | Market:  28.4% (  9.6%) | Wins: 39.0% | eps:  0.007\n",
      " 300 | 01:08:35 | Agent:   5.7% (-17.8%) | Market:  31.0% ( 46.1%) | Wins: 36.0% | eps:  0.006\n",
      " 310 | 01:11:53 | Agent:   6.9% (  9.7%) | Market:  31.0% ( 36.7%) | Wins: 36.0% | eps:  0.005\n",
      " 320 | 01:15:12 | Agent:   8.6% (  2.7%) | Market:  30.9% ( 40.5%) | Wins: 36.0% | eps:  0.005\n",
      " 330 | 01:18:32 | Agent:   9.3% ( 13.8%) | Market:  32.3% ( 38.6%) | Wins: 34.0% | eps:  0.004\n",
      " 340 | 01:21:52 | Agent:   9.9% ( 22.0%) | Market:  41.8% ( 79.7%) | Wins: 30.0% | eps:  0.004\n",
      " 350 | 01:25:16 | Agent:  17.7% ( 77.4%) | Market:  42.4% ( 35.0%) | Wins: 35.0% | eps:  0.004\n",
      " 360 | 01:28:39 | Agent:  15.8% ( 18.8%) | Market:  39.9% (  6.4%) | Wins: 33.0% | eps:  0.003\n",
      " 370 | 01:32:04 | Agent:  17.5% ( 37.4%) | Market:  40.8% ( 30.6%) | Wins: 34.0% | eps:  0.003\n",
      " 380 | 01:35:31 | Agent:  19.2% ( 29.1%) | Market:  39.3% ( 69.3%) | Wins: 37.0% | eps:  0.003\n",
      " 390 | 01:38:57 | Agent:  21.0% ( 16.7%) | Market:  42.6% ( 42.7%) | Wins: 37.0% | eps:  0.002\n",
      " 400 | 01:42:26 | Agent:  23.5% (  7.4%) | Market:  40.2% ( 22.7%) | Wins: 40.0% | eps:  0.002\n",
      " 410 | 01:45:55 | Agent:  23.6% ( 10.7%) | Market:  42.3% ( 57.8%) | Wins: 39.0% | eps:  0.002\n",
      " 420 | 01:49:25 | Agent:  30.1% ( 67.7%) | Market:  38.6% (  2.7%) | Wins: 43.0% | eps:  0.002\n",
      " 430 | 01:52:57 | Agent:  29.3% (  5.3%) | Market:  36.7% ( 19.6%) | Wins: 44.0% | eps:  0.002\n",
      " 440 | 01:56:28 | Agent:  28.7% ( 16.8%) | Market:  30.4% ( 17.3%) | Wins: 47.0% | eps:  0.001\n",
      " 450 | 02:00:01 | Agent:  25.0% ( 39.5%) | Market:  31.8% ( 48.6%) | Wins: 45.0% | eps:  0.001\n",
      " 460 | 02:02:38 | Agent:  28.1% ( 50.3%) | Market:  38.0% ( 68.8%) | Wins: 45.0% | eps:  0.001\n",
      " 470 | 02:05:06 | Agent:  30.7% ( 62.9%) | Market:  37.1% ( 21.5%) | Wins: 45.0% | eps:  0.001\n",
      " 480 | 02:07:36 | Agent:  31.2% ( 35.0%) | Market:  35.9% ( 56.9%) | Wins: 45.0% | eps:  0.001\n",
      " 490 | 02:10:09 | Agent:  36.7% ( 71.0%) | Market:  31.6% ( -0.1%) | Wins: 50.0% | eps:  0.001\n",
      " 500 | 02:12:42 | Agent:  38.0% ( 20.5%) | Market:  32.3% ( 29.9%) | Wins: 51.0% | eps:  0.001\n",
      " 510 | 02:15:16 | Agent:  39.2% ( 23.2%) | Market:  30.2% ( 36.8%) | Wins: 53.0% | eps:  0.001\n",
      " 520 | 02:17:52 | Agent:  33.7% ( 12.0%) | Market:  32.8% ( 29.0%) | Wins: 51.0% | eps:  0.001\n",
      " 530 | 02:20:31 | Agent:  36.0% ( 28.7%) | Market:  33.1% ( 22.4%) | Wins: 53.0% | eps:  0.001\n",
      " 540 | 02:23:12 | Agent:  37.8% ( 34.7%) | Market:  33.1% ( 17.4%) | Wins: 53.0% | eps:  0.001\n",
      " 550 | 02:25:53 | Agent:  37.5% ( 36.7%) | Market:  33.2% ( 49.0%) | Wins: 53.0% | eps:  0.000\n",
      " 560 | 02:28:37 | Agent:  35.1% ( 26.3%) | Market:  29.9% ( 35.9%) | Wins: 53.0% | eps:  0.000\n",
      " 570 | 02:31:22 | Agent:  34.1% ( 53.1%) | Market:  31.1% ( 34.2%) | Wins: 52.0% | eps:  0.000\n",
      " 580 | 02:34:08 | Agent:  33.0% ( 23.9%) | Market:  33.4% ( 79.9%) | Wins: 49.0% | eps:  0.000\n",
      " 590 | 02:36:56 | Agent:  29.0% ( 30.6%) | Market:  37.0% ( 35.8%) | Wins: 47.0% | eps:  0.000\n",
      " 600 | 02:39:48 | Agent:  30.0% ( 31.0%) | Market:  39.2% ( 51.3%) | Wins: 45.0% | eps:  0.000\n",
      " 610 | 02:42:48 | Agent:  32.2% ( 45.1%) | Market:  38.5% ( 29.6%) | Wins: 45.0% | eps:  0.000\n",
      " 620 | 02:45:25 | Agent:  33.3% ( 23.2%) | Market:  39.6% ( 40.6%) | Wins: 45.0% | eps:  0.000\n",
      " 630 | 02:47:50 | Agent:  33.3% ( 28.0%) | Market:  40.7% ( 33.5%) | Wins: 45.0% | eps:  0.000\n",
      " 640 | 02:50:16 | Agent:  33.5% ( 37.5%) | Market:  44.5% ( 54.8%) | Wins: 42.0% | eps:  0.000\n",
      " 650 | 02:53:06 | Agent:  37.1% ( 72.3%) | Market:  40.2% (  6.4%) | Wins: 45.0% | eps:  0.000\n",
      " 660 | 02:56:55 | Agent:  39.8% ( 53.7%) | Market:  38.9% ( 22.9%) | Wins: 48.0% | eps:  0.000\n",
      " 670 | 03:00:10 | Agent:  39.9% ( 54.0%) | Market:  37.5% ( 20.2%) | Wins: 49.0% | eps:  0.000\n",
      " 680 | 03:03:13 | Agent:  38.8% ( 12.8%) | Market:  31.2% ( 16.4%) | Wins: 54.0% | eps:  0.000\n",
      " 690 | 03:06:19 | Agent:  36.9% ( 11.7%) | Market:  30.5% ( 29.1%) | Wins: 51.0% | eps:  0.000\n",
      " 700 | 03:09:27 | Agent:  37.1% ( 32.7%) | Market:  27.8% ( 24.7%) | Wins: 53.0% | eps:  0.000\n",
      " 710 | 03:13:05 | Agent:  36.6% ( 39.7%) | Market:  25.4% (  5.0%) | Wins: 57.0% | eps:  0.000\n",
      " 720 | 03:16:44 | Agent:  36.8% ( 26.0%) | Market:  25.5% ( 41.7%) | Wins: 55.0% | eps:  0.000\n",
      " 730 | 03:19:43 | Agent:  34.9% (  8.3%) | Market:  26.5% ( 44.2%) | Wins: 55.0% | eps:  0.000\n",
      " 740 | 03:22:23 | Agent:  34.0% ( 28.5%) | Market:  25.7% ( 46.5%) | Wins: 57.0% | eps:  0.000\n",
      " 750 | 03:25:04 | Agent:  32.1% ( 53.7%) | Market:  28.4% ( 33.3%) | Wins: 53.0% | eps:  0.000\n",
      " 760 | 03:27:47 | Agent:  29.1% ( 23.8%) | Market:  26.9% (  8.3%) | Wins: 52.0% | eps:  0.000\n",
      " 770 | 03:30:32 | Agent:  28.6% ( 48.4%) | Market:  28.1% ( 31.9%) | Wins: 50.0% | eps:  0.000\n",
      " 780 | 03:33:20 | Agent:  30.8% ( 34.5%) | Market:  28.0% ( 15.5%) | Wins: 50.0% | eps:  0.000\n",
      " 790 | 03:36:45 | Agent:  31.4% ( 18.0%) | Market:  29.0% ( 38.5%) | Wins: 51.0% | eps:  0.000\n",
      " 800 | 03:40:09 | Agent:  33.4% ( 53.2%) | Market:  29.3% ( 28.1%) | Wins: 52.0% | eps:  0.000\n",
      " 810 | 03:43:37 | Agent:  35.9% ( 64.6%) | Market:  35.6% ( 67.6%) | Wins: 49.0% | eps:  0.000\n",
      " 820 | 03:47:05 | Agent:  38.0% ( 47.2%) | Market:  34.7% ( 33.0%) | Wins: 52.0% | eps:  0.000\n",
      " 830 | 03:50:52 | Agent:  37.6% (  3.9%) | Market:  30.3% (  0.7%) | Wins: 51.0% | eps:  0.000\n",
      " 840 | 03:53:58 | Agent:  41.5% ( 67.7%) | Market:  26.7% (  9.7%) | Wins: 53.0% | eps:  0.000\n",
      " 850 | 03:57:00 | Agent:  38.7% ( 25.5%) | Market:  26.2% ( 28.5%) | Wins: 53.0% | eps:  0.000\n",
      " 860 | 04:00:53 | Agent:  39.5% ( 31.5%) | Market:  27.7% ( 23.3%) | Wins: 52.0% | eps:  0.000\n",
      " 870 | 04:04:29 | Agent:  39.7% ( 50.4%) | Market:  24.0% ( -4.8%) | Wins: 55.0% | eps:  0.000\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 880 | 04:08:14 | Agent:  42.0% ( 58.4%) | Market:  23.8% ( 13.1%) | Wins: 56.0% | eps:  0.000\n",
      " 890 | 04:12:21 | Agent:  45.3% ( 50.2%) | Market:  22.2% ( 22.3%) | Wins: 57.0% | eps:  0.000\n",
      " 900 | 04:17:10 | Agent:  46.7% ( 67.2%) | Market:  22.0% ( 26.5%) | Wins: 58.0% | eps:  0.000\n",
      " 910 | 04:22:09 | Agent:  43.0% ( 27.9%) | Market:  15.5% (  2.9%) | Wins: 61.0% | eps:  0.000\n",
      " 920 | 04:27:13 | Agent:  44.6% ( 63.5%) | Market:  16.9% ( 46.4%) | Wins: 59.0% | eps:  0.000\n",
      " 930 | 04:32:23 | Agent:  49.0% ( 47.4%) | Market:  15.2% (-16.4%) | Wins: 63.0% | eps:  0.000\n",
      " 940 | 04:37:45 | Agent:  45.1% ( 29.3%) | Market:  15.8% ( 15.7%) | Wins: 62.0% | eps:  0.000\n",
      " 950 | 04:43:02 | Agent:  55.1% (125.2%) | Market:  17.2% ( 43.3%) | Wins: 64.0% | eps:  0.000\n",
      " 960 | 04:48:08 | Agent:  54.2% ( 22.8%) | Market:  21.4% ( 65.3%) | Wins: 60.0% | eps:  0.000\n",
      " 970 | 04:52:16 | Agent:  52.8% ( 36.4%) | Market:  22.2% (  2.4%) | Wins: 60.0% | eps:  0.000\n",
      " 980 | 04:57:31 | Agent:  53.3% ( 62.8%) | Market:  22.9% ( 20.5%) | Wins: 58.0% | eps:  0.000\n",
      " 990 | 05:02:54 | Agent:  53.0% ( 47.0%) | Market:  19.9% ( -7.9%) | Wins: 59.0% | eps:  0.000\n",
      "1000 | 05:08:19 | Agent:  51.4% ( 51.9%) | Market:  17.6% (  3.5%) | Wins: 58.0% | eps:  0.000\n"
     ]
    }
   ],
   "source": [
    "start = time()\n",
    "results = []\n",
    "for episode in range(1, max_episodes + 1):\n",
    "    this_state = trading_environment.reset()\n",
    "    for episode_step in range(max_episode_steps):\n",
    "        action = ddqn.epsilon_greedy_policy(this_state.reshape(-1, state_dim))\n",
    "        next_state, reward, done, _ = trading_environment.step(action)\n",
    "    \n",
    "        ddqn.memorize_transition(this_state, \n",
    "                                 action, \n",
    "                                 reward, \n",
    "                                 next_state, \n",
    "                                 0.0 if done else 1.0)\n",
    "        if ddqn.train:\n",
    "            ddqn.experience_replay()\n",
    "        if done:\n",
    "            break\n",
    "        this_state = next_state\n",
    "\n",
    "    result = trading_environment.env.simulator.result()\n",
    "    final = result.iloc[-1]\n",
    "\n",
    "    nav = final.nav * (1 + final.strategy_return)\n",
    "    navs.append(nav)\n",
    "\n",
    "    market_nav = final.market_nav\n",
    "    market_navs.append(market_nav)\n",
    "\n",
    "    diff = nav - market_nav\n",
    "    diffs.append(diff)\n",
    "    if episode % 10 == 0:\n",
    "        track_results(episode, np.mean(navs[-100:]), np.mean(navs[-10:]), \n",
    "                      np.mean(market_navs[-100:]), np.mean(market_navs[-10:]), \n",
    "                      np.sum([s > 0 for s in diffs[-100:]])/min(len(diffs), 100), \n",
    "                      time() - start, ddqn.epsilon)\n",
    "    if len(diffs) > 25 and all([r > 0 for r in diffs[-25:]]):\n",
    "        print(result.tail())\n",
    "        break\n",
    "\n",
    "trading_environment.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Store Results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-23T00:03:36.248773Z",
     "start_time": "2020-06-23T00:03:36.238411Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Int64Index: 1000 entries, 1 to 1000\n",
      "Data columns (total 4 columns):\n",
      " #   Column             Non-Null Count  Dtype  \n",
      "---  ------             --------------  -----  \n",
      " 0   Agent              1000 non-null   float64\n",
      " 1   Market             1000 non-null   float64\n",
      " 2   Difference         1000 non-null   float64\n",
      " 3   Strategy Wins (%)  901 non-null    float64\n",
      "dtypes: float64(4)\n",
      "memory usage: 39.1 KB\n"
     ]
    }
   ],
   "source": [
    "results = pd.DataFrame({'Episode': list(range(1, episode+1)),\n",
    "                        'Agent': navs,\n",
    "                        'Market': market_navs,\n",
    "                        'Difference': diffs}).set_index('Episode')\n",
    "\n",
    "results['Strategy Wins (%)'] = (results.Difference > 0).rolling(100).sum()\n",
    "results.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-23T00:03:36.273693Z",
     "start_time": "2020-06-23T00:03:36.250683Z"
    }
   },
   "outputs": [],
   "source": [
    "results.to_csv(results_path / 'results.csv', index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-23T00:03:36.579693Z",
     "start_time": "2020-06-23T00:03:36.274946Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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4XK5qKioGF21oqoq99xzD0uWLAlXdiGEEFxAkQshhNC3oFMrQggh9E2KXAghIpwUuRBCRLgJU+SNjY3MnTsXj8ejdZSwGBwc5JFHHmHp0qVUVFRQW1urdaSQUhSFlStXUlFRwbJly2hubtY6Ulj4fD6++c1vcv/993PvvffyzjvvaB0prHp6eli0aBGNjY1aR9HUhNg0y+Fw8Oyzz2KxTJz9kl9++WXmz5/Pgw8+SFNTEytWrOCNN97QOlbInG8riWj2+9//npSUFJ577jnsdjt33XUXn/nMZ7SOFRY+n4+VK1cSFye3tov6Ebmqqjz11FN84xvfID4+Xus4YfPggw9SWVkJQCAQIDY2ujcuOt9WEtHspptu4utf//roxybTxNkf/Nlnn6WyspKsrCyto2guqkbkmzdvZsOGDWc8lpubyy233MKMGTM0ShV6Y33da9asYdasWXR1dfHNb36TJ554QqN04eFwOLDZbKMfm0wm/H7/6FXI0SohIQEY/vr/8R//kccee0zjROHx+uuvk5aWRnl5OS+99JLWcTQX9evIFy9eTHb28CY1dXV1zJo1i1dffVXjVOFx8OBBvvGNb/Av//Ivo3vlRKu1a9dyxRVXcMsttwCwcOHC0SuSo93x48f52te+NjpPPhEsWbIEg8GAwWBg//79TJ06lfXr14d851XdUieQ66+/XnW73VrHCItDhw6pN954o7p//36to4TF22+/rX7rW99SVVVVa2tr1YceekjjROHR1dWl3nTTTeq2bdu0jqKZpUuXqocPH9Y6hqai+/fOCez555/H6/XyzDPPAMMbnEXzyb/FixezdetWKisrR7eSmAh++MMfMjAwwIsvvsiLL74IwI9//GM5ATjBRP3UihBCRLuoX7UihBDRTopcCCEinBS5EEJEOClyIYSIcFLkQggR4WT5oYhIO3bs4LHHHmPatGmoqorf72f58uUUFhbyzjvv8Oijj/Lqq6/y2muv8eUvf5n333+fo0ePsnbtWoqLi7WOL8S4kuWHIiLt2LGDjRs38p3vfAcYvvH3smXLeOaZZ5g5cyYwvN/M448/zvTp07n22mvZtm2blpGFCBkZkYuokJCQQEVFBatXryY7O5v58+dTX1/Pk08+SUpKCgMDA3zlK1/hv/7rv/i3f/s3mpubURSFxx57jKuvvprbbruNqVOnYrFY+Pd//3eefPJJ7HY7AN/+9reZPn06N9xwA3PmzOHIkSOkp6fzve99D5/Px+OPP057ezs+n4+nnnqK0tLSMV9DiFCRIhdRIz09HbvdTnZ2NhUVFbz55pusWrWK4uJiFixYwPr16/nlL39Jamoqa9aswW63s3TpUv7whz/gcrn46le/yqWXXspzzz3H/Pnzuf/++zl69CiPP/44v/rVr2hpaWHDhg3k5ORQWVnJnj17qKurIy8vj+985zs0NDSwbds29u/fP+ZrCBEqUuQiarS3t3PHHXdw6NChcz6noaGBmpoadu/eDYDf7x8deRcWFo4+Z/v27bz11lsADAwMAJCamkpOTg4AOTk5eDwempqaWLhwIQAlJSWUlJSwatWqMV8jNTU1BF+1EFLkIko4HA42b97MkiVLzvu8oqIisrOzeeSRR3C73axfv57k5GQAjEbj6HPuuOMObr/9dnp6eti8eTMABoPhrM9XXFzMnj17+OxnP0tLSwsvvPACV1xxxTlfQ4hQkCIXEWv79u0sW7YMo9FIIBDgH/7hH0hOTmbHjh3n/DeVlZV8+9vfZunSpTgcDu6///7RAh/xyCOP8OSTT/Laa6/hcDh49NFHz/v5nnjiCZYuXUogEOCJJ55g+vTpQV9DiPEkq1aEECLCyTBBCCEinBS5EEJEOClyIYSIcFLkQggR4aTIhRAiwkmRCyFEhJMiF0KICPf/AbUSOsk9UyLvAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "with sns.axes_style('white'):\n",
    "    sns.distplot(results.Difference)\n",
    "    sns.despine()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Evaluate Results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-23T00:03:36.585823Z",
     "start_time": "2020-06-23T00:03:36.580808Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Int64Index: 1000 entries, 1 to 1000\n",
      "Data columns (total 4 columns):\n",
      " #   Column             Non-Null Count  Dtype  \n",
      "---  ------             --------------  -----  \n",
      " 0   Agent              1000 non-null   float64\n",
      " 1   Market             1000 non-null   float64\n",
      " 2   Difference         1000 non-null   float64\n",
      " 3   Strategy Wins (%)  901 non-null    float64\n",
      "dtypes: float64(4)\n",
      "memory usage: 39.1 KB\n"
     ]
    }
   ],
   "source": [
    "results.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following diagram shows the rolling average of agent and market returns over 100 periods on the left, and the share of the last 100 periods the agent outperformed the market on the right. It uses AAPL stock data for which there are some 9,000 daily price and volume observations. Training stopped after 14,000 trading periods when the agent beat the market 10 consecutive times.\n",
    "\n",
    "It shows how the agent's performance improves significantly while exploring at a higher rate over the first ~3,000 periods (that is, years) and approaches a level where it outperforms the market around 40 percent of the time, despite transaction costs. In a few instances, it beats the market about half the time out of 100 periods:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-06-23T00:03:37.361710Z",
     "start_time": "2020-06-23T00:03:36.587097Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1008x288 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axes = plt.subplots(ncols=2, figsize=(14, 4), sharey=True)\n",
    "\n",
    "df1 = (results[['Agent', 'Market']]\n",
    "       .sub(1)\n",
    "       .rolling(100)\n",
    "       .mean())\n",
    "df1.plot(ax=axes[0],\n",
    "         title='Annual Returns (Moving Average)',\n",
    "         lw=1)\n",
    "\n",
    "df2 = results['Strategy Wins (%)'].div(100).rolling(50).mean()\n",
    "df2.plot(ax=axes[1],\n",
    "         title='Agent Outperformance (%, Moving Average)')\n",
    "\n",
    "for ax in axes:\n",
    "    ax.yaxis.set_major_formatter(\n",
    "        FuncFormatter(lambda y, _: '{:.0%}'.format(y)))\n",
    "    ax.xaxis.set_major_formatter(\n",
    "        FuncFormatter(lambda x, _: '{:,.0f}'.format(x)))\n",
    "axes[1].axhline(.5, ls='--', c='k', lw=1)\n",
    "\n",
    "sns.despine()\n",
    "fig.tight_layout()\n",
    "fig.savefig(results_path / 'performance', dpi=300)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Summary"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This relatively simple agent uses limited information beyond the latest market data and the reward signal compared to the machine learning models we covered elsewhere in this book. Nonetheless, it learns to make a profit and approach the market (after training on several thousand year's worth of data, which takes around 30 minutes).\n",
    "\n",
    "Keep in mind that using a single stock also increase the risk of overfitting the data by a lot. You can test your trained agent on new data using the saved model (see the notebook on the Lunar Lander).\n",
    "\n",
    "In conclusion, we have demonstrated the mechanics of setting up a RL trading environment and experimented with a basic agent that uses a small number of technical indicators. You should try to extend both the environment and the agent so that you can choose from several assets, size their positions, and manage risks.\n",
    "\n",
    "More specifically, the environment samples a stock price time series for a single ticker from a random start date to simulate a trading period of 252 days, or 1 year (default). The agent has three options, that is, buying (long), short, or exiting its position, and faces a 10bps trading plus a 1bps time cost per period."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:ml4t-dl]",
   "language": "python",
   "name": "conda-env-ml4t-dl-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": true,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "230.906px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
